﻿using SD.Common.PoweredByLee;
using SlamDunk.CMS.BLL;
using SlamDunk.CMS.Model.DataModel;
using SlamDunk.CMS.Model.FormatModel;
using SlamDunk.CMS.Model.ViewModel;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Web;
using System.Web.Mvc;
using System.Web.SessionState;

namespace SlamDunk.CMS.UI
{
    /// <summary>
    /// MVC表现层全局操作上下文
    /// </summary>
    public sealed class OperateContext
    {
        #region 常量
        private const string CurrentUserKey = "CurrentUser";                            //当前用户对象Session键
        private const string UserNameCookieKey = "UserName";                      //当前用户Id Cookie键
        private const string UserPwdCookieKey = "UserPwd";                           //当前用户Pwd Cookie键
        private const string MenuListKey = "MenuList";
        private const string ChannelListKey = "ChannelList";
        #endregion

        #region 实例化所需要的业务层对象
        /// <summary>
        /// 实例化所需要的业务层对象
        /// </summary>
        private readonly UserBll UserBll = new UserBll();
        private readonly MenusBll MenuBll = new MenusBll();
        private readonly ChannelBll ChannelBll = new ChannelBll();
        private readonly ArticleBll ArticleBll = new ArticleBll();
        #endregion

        #region 静态当前上下文对象属性 Current，类似HttpContext.Current
        /// <summary>
        /// 将构造方法私有化
        /// </summary>
        private OperateContext() { }

        /// <summary>
        /// 当前OperateContext实例，类似HttpContext.Current
        /// </summary>
        public static OperateContext Current
        {
            get
            {
                //从线程缓存中取，如果没有new一个，然后再存入线程缓存
                OperateContext context = CallContext.GetData(typeof(OperateContext).Name) as OperateContext;
                if (context == null)
                {
                    context = new OperateContext();
                    CallContext.SetData(typeof(OperateContext).Name, context);
                }
                return context;
            }
        }
        #endregion

        #region 便捷访问属性—HttpContext/Session/Response/Request
        /// <summary>
        /// 当前HttpContext对象
        /// </summary>
        public HttpContext ContextHttp
        {
            get
            {
                return HttpContext.Current;
            }
        }
        /// <summary>
        /// 当前Session对象
        /// </summary>
        public HttpSessionState Session
        {
            get
            {
                return this.ContextHttp.Session;
            }
        }
        /// <summary>
        /// 当前Request对象
        /// </summary>
        public HttpRequest Request
        {
            get
            {
                return HttpContext.Current.Request;
            }
        }
        /// <summary>
        /// 当前Response对象
        /// </summary>
        public HttpResponse Response
        {
            get
            {
                return this.ContextHttp.Response;
            }
        }
        #endregion

        #region Session——当前登录用户对象属性 CurrentUser
        /// <summary>
        /// 当前登录用户对象
        /// </summary>
        public User CurrentUser
        {
            get
            {
                return this.Session[CurrentUserKey] as User;
            }
            set
            {
                this.Session[CurrentUserKey] = value;
            }
        }
        #endregion

        #region Session——菜单集合属性 MenuList
        /// <summary>
        /// 当前登录用户的菜单集合
        /// </summary>
        public List<Menus> MenuList
        {
            get
            {
                return (this.Session[MenuListKey] as List<Menus>).OrderBy(x => x.Sort).ToList();
            }
            set
            {
                this.Session[MenuListKey] = value;
            }
        }
        #endregion

        #region Session——栏目集合属性 ChannelList
        /// <summary>
        /// 栏目集合属性
        /// </summary>
        public List<Channel> ChannelList
        {
            get
            {
                return (this.Session[ChannelListKey] as List<Channel>).OrderBy(x => x.Sort).ToList();
            }
            set
            {
                this.Session[ChannelListKey] = value;
            }
        }
        #endregion

        #region Session——当前登录用户的菜单Json字符串 MainMenuTree
        /// <summary>
        /// 当前登录用户的菜单Json字符串
        /// </summary>
        public string MainMenuTree
        {
            get
            {
                //1.实例化主菜单
                List<TreeModel> mainMenu = new List<TreeModel>();
                //2.定义顶级菜单——公司名称
                TreeModel company = new TreeModel() { text = ConfigurationManager.AppSettings["CompanyName"] };
                company.children = new List<TreeModel>();
                //3.文章管理部分
                company.children.AddRange(this.ChannelListToTree(this.ChannelList, 0));
                //4.普通菜单部分
                company.children.AddRange(this.MenuListToTree(this.MenuList, 0));
                mainMenu.Add(company);
                return mainMenu.ToJson();
            }
        }
        #endregion

        #region Cookie——用户名 UserNameCookie
        /// <summary>
        /// 存放用户名的Cookie
        /// </summary>
        public string UserNameCookie
        {
            get
            {
                //获取本地用户名Cookie
                HttpCookie cookieUserName = this.Request.Cookies[UserNameCookieKey];
                //判断是否存在
                if (cookieUserName != null && !string.IsNullOrEmpty(cookieUserName.Value))
                {
                    //cookie中有值，返回
                    return cookieUserName.Value;
                }
                else
                {
                    //cookie中无值，返回null
                    return null;
                }
            }
            set
            {
                //存放用户名的cookie
                HttpCookie cookieUserName = new HttpCookie(UserNameCookieKey, value);
                cookieUserName.Expires = DateTime.Now.AddDays(7);                                               //设置过期时间
                this.Response.Cookies.Add(cookieUserName);                                                                   //发送至客户端
            }
        }
        #endregion

        #region Cookie——用户密码 UserPwdCookie
        /// <summary>
        /// 存放用户密码的Cookie
        /// </summary>
        public string UserPwdCookie
        {
            get
            {
                //获取本地密码Cookie
                HttpCookie cookiePwd = this.Request.Cookies[UserPwdCookieKey];
                //判断是否存在
                if (cookiePwd != null && !string.IsNullOrEmpty(cookiePwd.Value))
                {
                    //cookie中有值，返回
                    return cookiePwd.Value;
                }
                else
                {
                    //cookie中无值，返回null
                    return null;
                }
            }
            set
            {
                //存放密码的cookie值为原始密码经过MD5加密
                HttpCookie cookiePwd = new HttpCookie(UserPwdCookieKey, value.ToMD5());
                cookiePwd.Expires = DateTime.Now.AddDays(7);                                               //设置过期时间
                this.Response.Cookies.Add(cookiePwd);                                                                   //发送至客户端
            }
        }
        #endregion

        #region JsonModel统一处理方法 JsonModel
        /// <summary>
        /// JsonModel统一处理方法
        /// </summary>
        /// <param name="data">返回客户端数据</param>
        /// <param name="status">返回客户端状态码</param>
        /// <param name="message">返回客户端消息</param>
        /// <param name="returnUrl">返回客户端重定向url地址</param>
        /// <returns>返回客户端JsonResult</returns>
        public JsonResult JsonModel(object data, int status, string message, string returnUrl)
        {
            JsonModel jsonModel = new JsonModel()
            {
                Data = data,
                Status = status,
                Message = message,
                ReturnUrl = returnUrl
            };
            JsonResult jr = new JsonResult()
            {
                Data = jsonModel,
                JsonRequestBehavior = JsonRequestBehavior.AllowGet
            };
            return jr;
        }
        public JsonResult JsonModel(int status, string message)
        {
            return this.JsonModel(null, status, message, null);
        }
        public JsonResult JsonModel(object data, int status, string message)
        {
            return this.JsonModel(data, status, message, null);
        }
        public JsonResult JsonModel(int status, string message, string returnUrl)
        {
            return this.JsonModel(null, status, message, returnUrl);
        }
        #endregion

        #region 校验用户登录方法 CheckLogin
        /// <summary>
        /// 校验用户登录
        /// </summary>
        /// <param name="userView">用户视图模型对象</param>
        /// <returns>返回客户端JsonResult</returns>
        public JsonResult CheckLogin(UserViewForLogin userView)
        {
            //1.创建空用户实体数据模型
            User currentUser = null;
            //2.获取业务层校验登录结果
            bool loginSuccess = this.UserBll.CheckLogin(userView.UserName, userView.Password, out currentUser);
            //3.根据不同结果返回不同JsonResult
            if (loginSuccess)
            {
                //将用户对象存入上下文当前用户属性中
                Current.CurrentUser = currentUser;
                //加载菜单，并存入上下文菜单属性中
                this.MenuList = this.MenuBll.GetModelList();
                this.ChannelList = this.ChannelBll.GetModelList();
                //判断用户是否记住密码
                if (userView.IsRemember)
                {
                    //设置cookie——用户名
                    Current.UserNameCookie = userView.UserName;
                    //设置cookie——用户密码
                    Current.UserPwdCookie = userView.Password;
                }
                //返回JsonResult
                return Current.JsonModel(1, string.Format("登录成功！欢迎您，{0}！", currentUser.RealName), "/Admin/Home/Index");
            }

            return Current.JsonModel(3, "用户名密码错误！");
        }
        #endregion

        #region 校验当前用户是否登录方法 IsLogin
        /// <summary>
        /// 校验当前用户是否登录
        /// </summary>
        /// <returns>是否登录</returns>
        public bool IsLogin()
        {
            //1.校验Session中的值
            if (this.CurrentUser == null)     //Session中未存储用户
            {
                //2.校验Cookie。获取cookie中的用户名和密码
                string safeUName = this.UserNameCookie;
                string safePwd = this.UserPwdCookie;
                //3.校验是否为空
                if (!string.IsNullOrEmpty(safeUName) && !string.IsNullOrEmpty(safePwd))              //Cookie存在
                {
                    //4.调用业务层校验
                    User user = null;
                    if (this.UserBll.CheckCookieLogin(safeUName, safePwd, out user))       //cookie存在且正确
                    {
                        this.CurrentUser = user;            //将user赋值给当前用户对象属性
                        //加载菜单，并存入上下文菜单属性中
                        this.MenuList = this.MenuBll.GetModelList();
                        this.ChannelList = this.ChannelBll.GetModelList();
                        return true;
                    }
                    else            //cookie存在但不正确
                    {
                        return false;
                    }
                }
                else               //Cookie丢失
                {
                    return false;
                }
            }
            else                   //Session中已存储用户
            {
                return true;
            }
        }
        #endregion

        #region 将菜单集合转换EasyUI树形集合方法 MenuListToTree
        /// <summary>
        /// 将菜单集合转换EasyUI树形集合方法 MenuListToTree
        /// </summary>
        /// <param name="menuList">菜单集合</param>
        /// <param name="pId">父Id</param>
        /// <returns>EasyUI树形集合</returns>
        public List<TreeModel> MenuListToTree(List<Menus> menuList, int pId)
        {
            //1.创建TreeModel集合
            List<TreeModel> menuTree = new List<TreeModel>();
            //2.遍历菜单集合
            foreach (Menus menu in menuList)
            {
                //3.筛选集合中PId等于给定pId的菜单实体
                if (menu.PId == pId)
                {
                    //4.将菜单实体转换为TreeModel
                    TreeModel treeModel = menu.ToTreeNode();
                    //5.在树集合中添加转换后的TreeModel
                    menuTree.Add(treeModel);
                    //6.递归查询子节点
                    treeModel.children = this.MenuListToTree(menuList, treeModel.id);
                }
            }
            //7.返回TreeModel集合
            return menuTree;
        }
        #endregion

        #region 将栏目集合转换EasyUI树形集合方法 ChannelListToTree
        /// <summary>
        /// 将栏目集合转换EasyUI树形集合方法 ChannelListToTree
        /// </summary>
        /// <param name="channelList">栏目集合</param>
        /// <param name="pId">父Id</param>
        /// <returns>EasyUI树形集合</returns>
        public List<TreeModel> ChannelListToTree(List<Channel> channelList, int pId)
        {
            //1.创建TreeModel集合
            List<TreeModel> channelTree = new List<TreeModel>();
            //2.遍历栏目集合
            foreach (Channel channel in channelList)
            {
                //3.筛选集合中PId等于给定pId的栏目实体
                if (channel.PId == pId)
                {
                    //4.将栏目实体对象转换为TreeModel
                    TreeModel treeModel = channel.ToTreeNode();
                    //5.在树集合中添加转换后的TreeModel
                    channelTree.Add(treeModel);
                    //6.递归查询子节点
                    treeModel.children = this.ChannelListToTree(channelList, treeModel.id);
                }
            }
            //7.返回TreeModel集合
            return channelTree;
        }
        #endregion

        #region 文章更新视图模型转换为数据模型方法
        /// <summary>
        /// 文章更新视图模型转换为数据模型方法
        /// </summary>
        /// <param name="model">文章更新视图模型对象</param>
        /// <returns>文章数据模型对象</returns>
        public Article ToDataModel(ArticleViewForUpdate model)
        {
            Article dataModel = this.ArticleBll.GetModel(model.Id);
            dataModel.UserId = model.UserId;
            dataModel.Title = model.Title;
            dataModel.Intitle = model.Intitle;
            dataModel.SubTitle = model.SubTitle;
            dataModel.Author = model.Author;
            dataModel.Source = model.Source;
            dataModel.Content = model.Content;
            dataModel.IsTop = model.IsTop;
            dataModel.ImagePath = model.ImagePath;
            dataModel.ThumbPath = model.ThumbPath;
            dataModel.Attachment = model.Attachment;
            return dataModel;
        }
        #endregion
    }
}
